package com.wyh.service.serviceImpl.groupOne.resource;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wyh.common.enums.ResourceEnum;
import com.wyh.common.exception.CustomException;
import com.wyh.common.utils.MasterDataRedisCache;
import com.wyh.domain.dto.gfive.LoginUser;
import com.wyh.domain.dto.groupOne.resource.*;


import com.wyh.domain.po.gfive.User;
import com.wyh.domain.po.groupOne.MasterDataUser;
import com.wyh.domain.po.groupOne.organization.MasterDataOrganization;
import com.wyh.domain.po.groupOne.projectabout.BuildingunitsPO;
import com.wyh.domain.po.groupOne.projectabout.ProjectPO;
import com.wyh.domain.po.groupOne.resource.MasterDataResource;
import com.wyh.domain.po.groupOne.threemeterAbout.Threemeter;
import com.wyh.domain.po.groupOne.threemeterAbout.Threemeter_Reading;
import com.wyh.domain.po.groupOne.resource.ResourceSub;
import com.wyh.domain.vo.groupOne.threemeterTree.MasterDataLayerVO_1;
import com.wyh.domain.vo.groupOne.utils.MasterDataDepartmentTree;
import com.wyh.domain.vo.groupOne.utils.MasterDataTreeNode;
import com.wyh.domain.vo.groupOne.utils.TreeSearch;
import com.wyh.domain.vo.groupOne.utils.TreeUtils.MasterDataDepartmentTreeUtils;
import com.wyh.domain.vo.groupOne.utils.TreeUtils.MasterDataDepartmentTreewithVersion;
import com.wyh.mapper.groupOne.resource.MasterDataResourceMapper;
import com.wyh.mapper.groupOne.resource.MasterDataResourceSubMapper;
import com.wyh.service.groupOne.resource.MasterDataResourceService;
import com.wyh.service.serviceImpl.groupOne.threemeterAbout.threemeterTree.MasterDataTreeGenerateMasterData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.YearMonth;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

import static com.wyh.common.enums.ResourceEnum.*;
import static com.wyh.common.enums.ResultCodeEnum.PARAM_ERROR;

@Service
public class MasterDataMasterDataResourceServiceImpl implements MasterDataResourceService {

    @Autowired
    private MasterDataResourceMapper masterDataResourceMapper;
    @Autowired
    private MasterDataResourceSubMapper masterDataResourceSubMapper;

    @Autowired
    private MasterDataTreeGenerateMasterData masterDataTreeGenerate;

    @Autowired
    private MasterDataRedisCache masterDataRedisCache;

    @Autowired
    private MasterDataDepartmentTreeUtils masterDataDepartmentTreeUtils;

    // 获取当前登录的用户的id的方法
    public User getCurrentUser() {
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        return loginUser.getUser();
    }

    /**
     * 新增
     */
    @Override
    @Transactional
    public int insert(MasterDataResource masterDataResource) {
        // 校验同一层级下资源名称是否重复
        MasterDataResource ResName = masterDataResourceMapper.selectByName(masterDataResource.getName(), masterDataResource.getBuildingid());
        if (ResName != null) {
            throw new CustomException(RESOURCE_NAME_REPEAT);
        }
        // 建筑面积不能小于套内面积校验
        if (masterDataResource.getBuildingarea() < masterDataResource.getInsidearea()) {
            throw new CustomException(ResourceEnum.BUILDING_AREA_NOT_LESS_THAN_INSIDE_AREA);
        }
        // 把当前用的名字获取当作最后的修改人, 把当前时间当作最后修改时间
        String modifier = getCurrentUser().getName();
        // 获取当前时间
        Date currentTime = new Date();
        // 设置日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将日期转换为字符串
        String currentTimeString = sdf.format(currentTime);
        try {
            Date time = sdf.parse(currentTimeString);
            masterDataResource.setModifier(modifier);
            masterDataResource.setChangeTime(time);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        int insertResult = masterDataResourceMapper.insertResource(masterDataResource);

        if (insertResult > 0) {
            // 删除 Redis 缓存树
            String redisKey = "wyh:MasterDataDepartmentTree:" + getCurrentUser().getId();
            masterDataRedisCache.deleteObject(redisKey);
            masterDataRedisCache.deleteObject("wyh:SearchResources:" + getCurrentUser().getId());

            // 从数据库加载最新的树并更新 Redis（假设有一个方法 `reloadAndCacheTree` 实现这一点）
            List<MasterDataTreeNode> updatedTree = reloadAndCacheTree();
            // 更新redis的资源表数据
            getAllResource();

            // 根据资源表的 type 决定 MasterDataTreeNode 的 type
            String nodeType = masterDataResource.getType() == 0 ? "room" : "parkingSpot";

            // 查找新插入的资源在树中的路径
            String path = getResourcePathInTree(masterDataResource.getId(), nodeType, updatedTree);

            // 更新数据库中的 `infoname` 字段
            masterDataResource.setInfoname(path);
            masterDataResourceMapper.updateInfoname(masterDataResource.getId(), path);
        }

        return insertResult;
    }

    // 加载全新的树的方法
    public List<MasterDataTreeNode> reloadAndCacheTree() {
        // 从数据库加载树数据
        masterDataDepartmentTreeUtils.updateDepartmentTree(getCurrentUser().getId());
        MasterDataDepartmentTreewithVersion departmentTree = masterDataDepartmentTreeUtils.getDepartmentTree(getCurrentUser().getId());
        List<MasterDataTreeNode> masterDataTreeNodes = departmentTree.getTreeNodes();
        //        List<MasterDataTreeNode> masterDataTreeNodes = treeGenerate.generateThreemeterTree();

        // 更新到 Redis
//        String redisKey = "wyh:MasterDataDepartmentTree:" + getCurrentUser().getId();
//        redisCache.setCacheObject(redisKey, masterDataTreeNodes);
        return masterDataTreeNodes;
    }

    // 获取资源的infoname（完整路径）的方法
    public String getResourcePathInTree(int resourceId, String nodeType, List<MasterDataTreeNode> tree) {
        // 构建节点映射
        Map<Integer, MasterDataTreeNode> nodeMap = new HashMap<>();
        for (MasterDataTreeNode root : tree) {
            TreeSearch.buildNodeMap(root, nodeMap);
        }

        // 查找符合 id 和 nodeType 的节点
        MasterDataTreeNode targetNode = findNodeByIdAndType(resourceId, nodeType, nodeMap);
        if (targetNode == null) {
            return null; // 资源节点不存在
        }

        // 生成资源节点的完整路径
        return MasterDataDepartmentTree.getPathFromNode(targetNode, nodeMap);
    }

    // 根据资源的id和node的type来查找结点的方法
    private MasterDataTreeNode findNodeByIdAndType(int id, String type, Map<Integer, MasterDataTreeNode> nodeMap) {
        // 遍历 nodeMap 中的所有节点，找到匹配 id 和 type 的节点
        for (MasterDataTreeNode node : nodeMap.values()) {
            if (node.getId() == id && type.equals(node.getType())) {
                return node;
            }
        }
        return null; // 没有找到匹配的节点
    }


    /**
     * 查询所有
     *
     * @param masterDataResource
     * @return
     */
    @Override
    public List<MasterDataResource> selectAll(MasterDataResource masterDataResource) {
        return masterDataResourceMapper.selectAll(masterDataResource);
    }

    /**
     * 修改
     *
     * @param masterDataResource
     * @return
     */
    @Override
    @Transactional
    public int updateById(MasterDataResource masterDataResource) {
        // 获取数据库中已存在的资源对象，用于检查其 isvirtual 状态
        MasterDataResource existingMasterDataResource = masterDataResourceMapper.selectById(masterDataResource.getId());
        // 判断资源是否被删除
        if (existingMasterDataResource == null) {
            throw new CustomException(HAS_DELETE);
        }
        // 判断资源是否停用
        if (existingMasterDataResource.getState() == 3) {
            throw new CustomException(HAS_STOP_TO_USER);
        }
        // 检查现有资源是否为非虚拟资源 (isvirtual == 1)
        if (existingMasterDataResource.getIsvirtual() == 1) {
            throw new CustomException(ResourceEnum.CANNOT_MODIFY_NON_VIRTUAL_TO_VIRTUAL);
        }
        // 把当前用的名字获取当作最后的修改人, 把当前时间当作最后修改时间
        String modifier = getCurrentUser().getName();
        // 获取当前时间
        Date currentTime = new Date();
        // 设置日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将日期转换为字符串
        String currentTimeString = sdf.format(currentTime);
        try {
            Date time = sdf.parse(currentTimeString);
            masterDataResource.setModifier(modifier);
            masterDataResource.setChangeTime(time);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        // 执行修改操作
        int updateFlag = masterDataResourceMapper.updateById(masterDataResource);
        // 删除 Redis 缓存树
        String redisKey = "wyh:MasterDataDepartmentTree:" + getCurrentUser().getId();
        masterDataRedisCache.deleteObject(redisKey);
        masterDataRedisCache.deleteObject("wyh:SearchResources:" + getCurrentUser().getId());

        // 从数据库加载最新的树并更新 Redis（假设有一个方法 `reloadAndCacheTree` 实现这一点）
        masterDataDepartmentTreeUtils.updateDepartmentTree(getCurrentUser().getId());
        // 更新redis的资源表数据
        getAllResource();
        return updateFlag;
    }

    @Override
    @Transactional
    public int deleteById(Integer id) {
        if (id == null) {
            throw new CustomException(PARAM_ERROR);
        }
        MasterDataResource masterDataResource1 = masterDataResourceMapper.selectById(id);
        // 判断资源是否被删除
        if (masterDataResource1 == null) {
            throw new CustomException(HAS_DELETE);
        }
        // 判断资源状态是不是未接房
        if (masterDataResource1.getState() == 0) {
            throw new CustomException(NOT_PICK_UP_ERROR);
        }
        // 判断资源是否停用
        if (masterDataResource1.getState() == 3) {
            throw new CustomException(HAS_STOP_TO_USER);
        }
        // 判断资源是否空置
        if (masterDataResource1.getState() != 1) {
            throw new CustomException(NOT_EMPTY_ERROR);
        }
        // 删除资源
        int delFlag = masterDataResourceMapper.deleteById(id);
        // 把当前用的名字获取当作最后的修改人, 把当前时间当作最后修改时间
        String modifier = getCurrentUser().getName();
        // 获取当前时间
        Date currentTime = new Date();
        // 设置日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 将日期转换为字符串
        String currentTimeString = sdf.format(currentTime);
        try {
            Date time = sdf.parse(currentTimeString);
            MasterDataResource masterDataResource = new MasterDataResource();
            masterDataResource.setId(id);
            masterDataResource.setModifier(modifier);
            masterDataResource.setChangeTime(time);
            masterDataResourceMapper.updateModifierAndTime(masterDataResource);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        // 删除 Redis 缓存树
        String redisKey = "wyh:MasterDataDepartmentTree:" + getCurrentUser().getId();
        masterDataRedisCache.deleteObject(redisKey);
        masterDataRedisCache.deleteObject("wyh:SearchResources:" + getCurrentUser().getId());

        // 从数据库加载最新的树并更新 Redis（假设有一个方法 `reloadAndCacheTree` 实现这一点）
        masterDataDepartmentTreeUtils.updateDepartmentTree(getCurrentUser().getId());
        // 更新redis的资源表数据
        getAllResource();
        return delFlag;
    }

    @Override
    @Transactional
    public List<ResourceDetailDTO> getAllDetails(MasterDataResourceTypeDTO masterDataResourceTypeDTO) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();

        Integer id = masterDataResourceTypeDTO.getId();
        String type = masterDataResourceTypeDTO.getType().toLowerCase(); // 将类型转换为小写

        switch (type) {
            case "organization":
                List<MasterDataOrganization> masterDataOrganizations = fetchSubOrganizationsIncludingSelf(id);
                if (masterDataOrganizations.size() == 0) {
                    // 假如用户点击根节点:天天集团,先去查下方有没有组织,没有
                    // 直接那用户前端点的传来的id,直接去查项目,就用这一个id
                    MasterDataOrganization org = masterDataResourceMapper.selectOrganization(id);
                    allDetails.addAll(getDetailsForOrganization(org, Arrays.asList(id)));
                } else {
                    // 传过来这个id查出来下面有组织
                    // 把所有组织的id(主键)收集
                    for (MasterDataOrganization org : masterDataOrganizations) {
                        List<Integer> organizationIds = new ArrayList<>();
                        organizationIds.add(org.getId());
                        allDetails.addAll(getDetailsForOrganization(org, organizationIds));
                    }
                }
                break;
            case "gardenarea": // 匹配小写的 "gardenarea"
                ProjectPO project1 = masterDataResourceMapper.selectProject(id);
                List<ProjectPO> projects = masterDataResourceMapper.selectAllProject(Arrays.asList(project1.getSuperiorid()));
                for (ProjectPO project : projects) {
                    MasterDataOrganization org = masterDataResourceMapper.selectOrganization(project.getSuperiorid());
                    allDetails.addAll(getDetailsForProject(project, org));
                }
                break;

            case "houses":
                ProjectPO project2 = masterDataResourceMapper.selectHouse(id);
                if (project2 != null) {
                    List<ProjectPO> houses = masterDataResourceMapper.selectAllHouse(Arrays.asList(project2.getSuperiorid()));
                    for (ProjectPO house : houses) {
                        ProjectPO garden = masterDataResourceMapper.selectProject(house.getSuperiorid());
                        MasterDataOrganization org = masterDataResourceMapper.selectOrganization(garden.getSuperiorid());
                        allDetails.addAll(getDetailsForHouse(house, garden, org));
                    }
                } else {
                    ProjectPO project3 = masterDataResourceMapper.selectOrganizationHouse(id);
                    if (project3 != null) {
                        List<ProjectPO> houses = masterDataResourceMapper.selectAllOrganizationHouse(Arrays.asList(project3.getSuperiorid()));
                        for (ProjectPO house : houses) {
                            MasterDataOrganization org = masterDataResourceMapper.selectOrganization(house.getSuperiorid());
                            allDetails.addAll(getDetailsForHouse(house, null, org));
                        }
                    }
                }
                break;
            case "building":
                BuildingunitsPO buildingunits = masterDataResourceMapper.selectBuilding(id);
                List<BuildingunitsPO> units = masterDataResourceMapper.selectAllBuildingunits(Arrays.asList(buildingunits.getParentid()));
                for (BuildingunitsPO unit : units) {
                    ProjectPO house = masterDataResourceMapper.selectHouse(unit.getParentid());
                    ProjectPO garden = masterDataResourceMapper.selectProject(house.getSuperiorid());
                    MasterDataOrganization org = masterDataResourceMapper.selectOrganization(garden.getSuperiorid());
                    allDetails.addAll(getDetailsForBuildingunits(unit, house, garden, org));
                }
                break;
            case "layer":
                MasterDataLayerVO_1 layer1 = masterDataResourceMapper.selectLayer(id);
                List<MasterDataLayerVO_1> layers = masterDataResourceMapper.selectAllLayer(Arrays.asList(layer1.getParentId()));
                for (MasterDataLayerVO_1 layer : layers) {
                    BuildingunitsPO building = masterDataResourceMapper.selectBuilding(layer.getParentId());
                    ProjectPO house = masterDataResourceMapper.selectHouse(building.getParentid());
                    ProjectPO garden = masterDataResourceMapper.selectProject(house.getSuperiorid());
                    MasterDataOrganization org = masterDataResourceMapper.selectOrganization(garden.getSuperiorid());
                    allDetails.addAll(getDetailsForLayer(layer, building, house, garden, org));
                }
                break;
            case "resource":
                List<MasterDataResource> masterDataResources = masterDataResourceMapper.selectAllResource(Arrays.asList(id));
                for (MasterDataResource masterDataResource : masterDataResources) {
                    allDetails.addAll(getDetailsForResource(masterDataResource));
                }
                break;
            default:
                throw new IllegalArgumentException("Invalid type: " + type);
        }

        return allDetails;
    }


    // 获取包括传入ID的组织及其所有下级组织
    private List<MasterDataOrganization> fetchSubOrganizationsIncludingSelf(int superiorId) {
        List<MasterDataOrganization> allMasterDataOrganizations = new ArrayList<>();
        // 获取当前组织
        MasterDataOrganization currentMasterDataOrganization = masterDataResourceMapper.selectOrganization(superiorId);
        if (currentMasterDataOrganization != null) {
            allMasterDataOrganizations.add(currentMasterDataOrganization);
        }

        // 递归获取下级组织
        List<MasterDataOrganization> subMasterDataOrganizations = fetchSubOrganizations(superiorId);
        allMasterDataOrganizations.addAll(subMasterDataOrganizations);
        return allMasterDataOrganizations;
    }

    // 递归方法获取下级组织并返回一个List集合
    private List<MasterDataOrganization> fetchSubOrganizations(int superiorId) {
        List<MasterDataOrganization> allMasterDataOrganizations = new ArrayList<>();
        List<MasterDataOrganization> subMasterDataOrganizations = masterDataResourceMapper.selectAllOrganization(superiorId);

        for (MasterDataOrganization org : subMasterDataOrganizations) {
            allMasterDataOrganizations.add(org);
            allMasterDataOrganizations.addAll(fetchSubOrganizations(org.getId()));
        }

        return allMasterDataOrganizations;
    }

    private List<ResourceDetailDTO> getDetailsForOrganization(MasterDataOrganization org, List<Integer> organizationIds) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();
        List<ProjectPO> projects = masterDataResourceMapper.selectAllProject(organizationIds);
        for (ProjectPO project : projects) {
            if (project.getType() == 1 && "Y".equals(project.getIsconnected())) {
                List<BuildingunitsPO> units = masterDataResourceMapper.selectAllBuildingunits(Arrays.asList(project.getId()));
                for (BuildingunitsPO unit : units) {
                    allDetails.addAll(getDetailsForBuildingunits(unit, project, null, org));
                }
            } else {
                allDetails.addAll(getDetailsForProject(project, org));
            }
        }
        return allDetails;
    }

    private List<ResourceDetailDTO> getDetailsForProject(ProjectPO project) {
        return getDetailsForProject(project, null);
    }

    private List<ResourceDetailDTO> getDetailsForProject(ProjectPO project, MasterDataOrganization org) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();
        List<ProjectPO> houses = masterDataResourceMapper.selectAllHouse(Arrays.asList(project.getId()));
        for (ProjectPO house : houses) {
            allDetails.addAll(getDetailsForHouse(house, project, org));
        }
        return allDetails;
    }

    private List<ResourceDetailDTO> getDetailsForHouse(ProjectPO house) {
        return getDetailsForHouse(house, null, null);
    }

    private List<ResourceDetailDTO> getDetailsForHouse(ProjectPO house, ProjectPO garden, MasterDataOrganization org) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();
        List<BuildingunitsPO> units = masterDataResourceMapper.selectAllBuildingunits(Arrays.asList(house.getId()));
        for (BuildingunitsPO unit : units) {
            allDetails.addAll(getDetailsForBuildingunits(unit, house, garden, org));
        }
        return allDetails;
    }

    private List<ResourceDetailDTO> getDetailsForBuildingunits(BuildingunitsPO unit) {
        return getDetailsForBuildingunits(unit, null, null, null);
    }

    private List<ResourceDetailDTO> getDetailsForBuildingunits(BuildingunitsPO unit, ProjectPO house, ProjectPO garden, MasterDataOrganization org) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();
        List<MasterDataLayerVO_1> layers = masterDataResourceMapper.selectAllLayer(Arrays.asList(unit.getId()));
        for (MasterDataLayerVO_1 layer : layers) {
            allDetails.addAll(getDetailsForLayer(layer, unit, house, garden, org));
        }
        return allDetails;
    }

    private List<ResourceDetailDTO> getDetailsForLayer(MasterDataLayerVO_1 layer) {
        return getDetailsForLayer(layer, null, null, null, null);
    }

    private List<ResourceDetailDTO> getDetailsForLayer(MasterDataLayerVO_1 layer, BuildingunitsPO building, ProjectPO house, ProjectPO garden, MasterDataOrganization org) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();
        List<MasterDataResource> masterDataResources = masterDataResourceMapper.selectAllResource(Arrays.asList(layer.getId()));
        for (MasterDataResource masterDataResource : masterDataResources) {
            allDetails.add(createResourceDetailDTO(org, garden, house, building, layer, masterDataResource));
        }
        return allDetails;
    }

    private List<ResourceDetailDTO> getDetailsForResource(MasterDataResource masterDataResource) {
        return getDetailsForResource(masterDataResource, null, null, null, null, null);
    }

    private List<ResourceDetailDTO> getDetailsForResource(MasterDataResource masterDataResource, MasterDataLayerVO_1 layer, BuildingunitsPO building, ProjectPO house, ProjectPO garden, MasterDataOrganization org) {
        List<ResourceDetailDTO> allDetails = new ArrayList<>();
        allDetails.add(createResourceDetailDTO(org, garden, house, building, layer, masterDataResource));
        return allDetails;
    }

    private ResourceDetailDTO createResourceDetailDTO(MasterDataOrganization org, ProjectPO garden, ProjectPO house, BuildingunitsPO building, MasterDataLayerVO_1 layer, MasterDataResource masterDataResource) {
        ResourceDetailDTO dto = new ResourceDetailDTO();
        dto.setId(masterDataResource.getId());
        dto.setOrganizationName(org != null ? org.getName() : null);
        dto.setRegion(garden != null ? garden.getName() : null);
        dto.setBuildingName(house != null ? house.getName() : null);
        dto.setBuildingNumber(building != null ? building.getName() : null);
        dto.setFloorNumber(layer != null ? layer.getName() : null);
        dto.setResourceNumber(masterDataResource.getNumber());
        dto.setResourceName(masterDataResource.getName());
        dto.setVirtual(masterDataResource.getIsvirtual() == 0);
        dto.setResourceType(masterDataResource.getType() == 0 ? "房屋" : "车位");
        dto.setResourceStatus(masterDataResource.getState() == 0 ? "未接房" : masterDataResource.getState() == 1 ? "空闲" : masterDataResource.getState() == 2 ? "已出租" : "失效");
        dto.setBuildingArea(masterDataResource.getBuildingarea() != null ? masterDataResource.getBuildingarea() : 0.0);
        dto.setInsideArea(masterDataResource.getInsidearea() != null ? masterDataResource.getInsidearea() : 0.0);
        return dto;
    }


    @Override
    public List<MasterDataOrganization> selectAllOrganization(Integer id) {
        return masterDataResourceMapper.selectAllOrganization(id);
    }

    // 生成资源管理菜单树的业务方法
    @Override
    public List<MasterDataTreeNode> generateResourceTree() {
        List<MasterDataTreeNode> tree = masterDataTreeGenerate.generateResourceTree();
        return tree;
    }

    // 模糊查询资源树的业务方法
    @Override
    public List<MasterDataTreeNode> searchResourceTree(String keyword) {
        // 获取树
        List<MasterDataTreeNode> tree = generateResourceTree();
        MasterDataTreeNode masterDataTreeNode = tree.get(0);
        List<MasterDataTreeNode> searchTree = TreeSearch.searchTree(masterDataTreeNode, keyword);
        return searchTree;
    }

    @Override
    @Transactional
    public void splitResource(ResourceSplitDTO resourceSplitDTO) {
        // 获取需要拆分的资源
        MasterDataResource masterDataResource = masterDataResourceMapper.selectById(resourceSplitDTO.getId());

        // 当前时间
        Date now = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = formatter.format(now);

        // 将变更前的资源加入资源子表
        ResourceSub resourceSubBefore = new ResourceSub();
        resourceSubBefore.setResourceid(masterDataResource.getId());
        resourceSubBefore.setNumber(masterDataResource.getNumber());
        resourceSubBefore.setName(masterDataResource.getName());
        resourceSubBefore.setBuildingarea(masterDataResource.getBuildingarea());
        resourceSubBefore.setInsidearea(masterDataResource.getInsidearea());
        resourceSubBefore.setChangeType(0); // 变更前的资源
        resourceSubBefore.setChangeTime(now); // 设置变更时间
        resourceSubBefore.setOperationType("split"); // 设置操作类型为split
        masterDataResourceSubMapper.insert(resourceSubBefore);

        // 校验新资源的建筑面积和套内面积
        if (resourceSplitDTO.getBuildingArea() > masterDataResource.getBuildingarea()) {
            throw new CustomException(BUILDING_AREA_EXCEEDS);
        }
        if (resourceSplitDTO.getInsideArea() > masterDataResource.getInsidearea()) {
            throw new CustomException(INSIDE_AREA_EXCEEDS);
        }
        if (resourceSplitDTO.getInsideArea() > resourceSplitDTO.getBuildingArea()) {
            throw new CustomException(INSIDE_AREA_EXCEEDS_BUILDING);
        }

        // 更新被拆分资源的面积
        masterDataResource.setBuildingarea(masterDataResource.getBuildingarea() - resourceSplitDTO.getBuildingArea());
        masterDataResource.setInsidearea(masterDataResource.getInsidearea() - resourceSplitDTO.getInsideArea());
        //从token中拿取当前用户的名称
        masterDataResource.setModifier(getCurrentUser().getName());
        masterDataResource.setChangeTime(now);

        // 将变更后的资源加入资源子表
        ResourceSub resourceSubAfter = new ResourceSub();
        resourceSubAfter.setResourceid(masterDataResource.getId());
        resourceSubAfter.setNumber(masterDataResource.getNumber());
        resourceSubAfter.setName(masterDataResource.getName());
        resourceSubAfter.setBuildingarea(masterDataResource.getBuildingarea());
        resourceSubAfter.setInsidearea(masterDataResource.getInsidearea());
        resourceSubAfter.setChangeType(1); // 变更后的资源
        resourceSubAfter.setChangeTime(now); // 设置变更时间
        resourceSubAfter.setOperationType("split"); // 设置操作类型为split
        masterDataResourceSubMapper.insert(resourceSubAfter);

        // 更新被拆分的资源
        masterDataResourceMapper.updateById(masterDataResource);

        // 创建新的资源
        MasterDataResource newMasterDataResource = new MasterDataResource();
        newMasterDataResource.setNumber(resourceSplitDTO.getResourceNumber());
        newMasterDataResource.setName(resourceSplitDTO.getResourceName());
        newMasterDataResource.setBuildingarea(resourceSplitDTO.getBuildingArea());
        newMasterDataResource.setInsidearea(resourceSplitDTO.getInsideArea());
        newMasterDataResource.setType(masterDataResource.getType());
        newMasterDataResource.setState(0); // 未接房状态
        newMasterDataResource.setIsvirtual(1); // 0是虚拟资源，1不是虚拟资源
        newMasterDataResource.setBuildingid(masterDataResource.getBuildingid());
        newMasterDataResource.setInfoname(resourceSplitDTO.getResourceName());
        //从token中拿取当前用户的名称
        newMasterDataResource.setModifier(getCurrentUser().getName());
        newMasterDataResource.setChangeTime(now);

        // 插入新的资源到资源子表
        ResourceSub resourceSubNew = new ResourceSub();
        resourceSubNew.setResourceid(masterDataResource.getId()); // 更新父id
        resourceSubNew.setNumber(newMasterDataResource.getNumber());
        resourceSubNew.setName(newMasterDataResource.getName());
        resourceSubNew.setBuildingarea(newMasterDataResource.getBuildingarea());
        resourceSubNew.setInsidearea(newMasterDataResource.getInsidearea());
        resourceSubNew.setChangeType(2); // 新的资源
        resourceSubNew.setChangeTime(now); // 设置变更时间
        resourceSubNew.setOperationType("split"); // 设置操作类型为split
        masterDataResourceSubMapper.insert(resourceSubNew);

        // 插入新的资源到资源表
        masterDataResourceMapper.insert(newMasterDataResource);
    }

    @Transactional
    public ResourceCombineShowDTO getCombineResource(Integer id) {
        //获取当前资源合并前信息
        ResourceSub latestCombineBeforeChange = masterDataResourceSubMapper.getLatestCombineBeforeChange(id);
        //获取当前资源合并后信息
        ResourceSub latestCombineAfterChange = masterDataResourceSubMapper.getLatestCombineAfterChange(id);
        //将合并前后的信息装人DTO中
        ResourceCombineShowDTO resourceCombineShowDTO = new ResourceCombineShowDTO();
        resourceCombineShowDTO.setBuildingareaBefore(latestCombineBeforeChange.getBuildingarea());
        resourceCombineShowDTO.setInsideareaBefore(latestCombineBeforeChange.getInsidearea());
        resourceCombineShowDTO.setBuildingareaAfter(latestCombineAfterChange.getBuildingarea());
        resourceCombineShowDTO.setInsideareaAfter(latestCombineAfterChange.getInsidearea());

        return resourceCombineShowDTO;
    }

    @Override
    @Transactional
    public List<MasterDataResource> selectLayerAllResource(Integer id) {
        //获取当前资源
        MasterDataResource masterDataResource = masterDataResourceMapper.selectById(id);
        //查询当前资源楼层下的所有资源
        List<MasterDataResource> list = masterDataResourceMapper.selectLayerAllResource(masterDataResource.getBuildingid());
        return list;
    }

    @Override
    @Transactional
    public void combineResource(ResourceCombineDTO resourceCombineDTO) {
        //获取当前资源
        MasterDataResource currentMasterDataResource = masterDataResourceMapper.selectById(resourceCombineDTO.getCurrentResourceId());
        // 初始化合并的建筑面积和套内面积
        Double totalBuildingArea = currentMasterDataResource.getBuildingarea();
        Double totalInsideArea = currentMasterDataResource.getInsidearea();
        // 当前时间
        Date now = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
        String formattedDateTime = formatter.format(now);
        // 创建合并前的资源子记录
        ResourceSub beforeMerge = new ResourceSub();
        beforeMerge.setResourceid(currentMasterDataResource.getId());
        beforeMerge.setName(currentMasterDataResource.getName());
        beforeMerge.setBuildingarea(currentMasterDataResource.getBuildingarea());
        beforeMerge.setInsidearea(currentMasterDataResource.getInsidearea());
        beforeMerge.setNumber(currentMasterDataResource.getNumber());
        beforeMerge.setChangeType(0); // 0表示合并前
        beforeMerge.setChangeTime(now);
        beforeMerge.setOperationType("merge"); // 表示合并操作
        masterDataResourceSubMapper.insert(beforeMerge);

        // 遍历选中的资源，累加建筑面积和套内面积，并将状态设为失效
        for (Integer resourceId : resourceCombineDTO.getSelectedResourceIds()) {
            MasterDataResource masterDataResource = masterDataResourceMapper.selectById(resourceId);
            totalBuildingArea += masterDataResource.getBuildingarea();
            totalInsideArea += masterDataResource.getInsidearea();

            // 更新选中资源的状态为失效
            //从token中拿取当前用户的名称
            masterDataResource.setModifier(getCurrentUser().getName());
            masterDataResource.setChangeTime(now);
            masterDataResource.setState(3);
            masterDataResourceMapper.updateById(masterDataResource);
        }

        // 更新当前资源的建筑面积和套内面积
        currentMasterDataResource.setBuildingarea(totalBuildingArea);
        currentMasterDataResource.setInsidearea(totalInsideArea);
        //从token中拿取当前用户的名称
        currentMasterDataResource.setModifier(getCurrentUser().getName());
        currentMasterDataResource.setChangeTime(now);
        masterDataResourceMapper.updateById(currentMasterDataResource);
        // 创建合并后的资源子记录
        ResourceSub afterMerge = new ResourceSub();
        afterMerge.setResourceid(currentMasterDataResource.getId());
        afterMerge.setName(currentMasterDataResource.getName());
        afterMerge.setBuildingarea(currentMasterDataResource.getBuildingarea());
        afterMerge.setInsidearea(currentMasterDataResource.getInsidearea());
        afterMerge.setNumber(currentMasterDataResource.getNumber());
        afterMerge.setChangeType(1); // 1表示合并后
        afterMerge.setChangeTime(now);
        afterMerge.setOperationType("merge"); // 表示合并操作
        masterDataResourceSubMapper.insert(afterMerge);
    }

    public ResourceSplitShowDTO getSplitResource(Integer id) {
        //获取当前资源变更前信息
        ResourceSub latestBeforeChange = masterDataResourceSubMapper.getLatestBeforeChange(id);
        //获取当前资源变更后信息
        ResourceSub latestAfterChange = masterDataResourceSubMapper.getLatestAfterChange(id);
        //获取当前资源拆分的资源信息
        ResourceSub latestNewResource = masterDataResourceSubMapper.getLatestNewResource(id);

        //将当前资源变更前,变更后,拆分的资源的信息放入DTO对象
        ResourceSplitShowDTO resourceSplitShowDTO = new ResourceSplitShowDTO();
        resourceSplitShowDTO.setBuildingareaBefore(latestBeforeChange.getBuildingarea());
        resourceSplitShowDTO.setInsideareaBefore(latestBeforeChange.getInsidearea());
        resourceSplitShowDTO.setBuildingareaAfter(latestAfterChange.getBuildingarea());
        resourceSplitShowDTO.setInsideareaAfter(latestAfterChange.getInsidearea());
        resourceSplitShowDTO.setNewNumber(latestNewResource.getNumber());
        resourceSplitShowDTO.setNewName(latestNewResource.getName());
        resourceSplitShowDTO.setNewBuildingarea(latestNewResource.getBuildingarea());
        resourceSplitShowDTO.setNewInsidearea(latestNewResource.getInsidearea());

        return resourceSplitShowDTO;
    }

    /**
     * 分页查询
     */
    public PageInfo<ResourceDetailDTO> selectPage(MasterDataResourceTypeDTO masterDataResourceTypeDTO) {
//        if (masterDataResourceTypeDTO.getPageNum() == null || masterDataResourceTypeDTO.getPageSize() == null) {
//            PageHelper.startPage(1, 10);
//        }

        List<ResourceDetailDTO> list = getAllDetails(masterDataResourceTypeDTO);
        return getPageInfo(list, masterDataResourceTypeDTO.getPageNum(), masterDataResourceTypeDTO.getPageSize());
    }

    // 分页处理方法
    private PageInfo<ResourceDetailDTO> getPageInfo(List<ResourceDetailDTO> masterDataUserList, int pageNum, int pageSize) {
        int total = masterDataUserList.size();
        int fromIndex = Math.min((pageNum - 1) * pageSize, total);
        int toIndex = Math.min(fromIndex + pageSize, total);

        List<ResourceDetailDTO> pageList = masterDataUserList.subList(fromIndex, toIndex);

        PageInfo<ResourceDetailDTO> pageInfo = new PageInfo<>(pageList);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotal(total);
        pageInfo.setPages((int) Math.ceil((double) total / pageSize));
        pageInfo.setSize(pageList.size());
        pageInfo.setStartRow(fromIndex);
        pageInfo.setEndRow(toIndex - 1);
        pageInfo.setIsFirstPage(pageNum == 1);
        pageInfo.setIsLastPage(pageNum == pageInfo.getPages());
        pageInfo.setHasPreviousPage(pageNum > 1);
        pageInfo.setHasNextPage(pageNum < pageInfo.getPages());

        int navigatePages = 8;
        int[] navigatePageNums = new int[Math.min(navigatePages, pageInfo.getPages())];
        for (int i = 0; i < navigatePageNums.length; i++) {
            navigatePageNums[i] = pageNum - (navigatePageNums.length / 2) + i;
            if (navigatePageNums[i] < 1) navigatePageNums[i] = i + 1;
            if (navigatePageNums[i] > pageInfo.getPages()) navigatePageNums[i] = pageInfo.getPages() - navigatePageNums.length + i + 1;
        }
        pageInfo.setNavigatePages(navigatePages);
        pageInfo.setNavigatepageNums(navigatePageNums);

        return pageInfo;
    }

    @Override
    public PageInfo<ResourceDetailDTO> selectByCondition(MasterDataResource masterDataResource) {
        List<ResourceDetailDTO> allResource = getAllResource(); // 假设这个方法从 Redis 获取所有资源数据
        List<ResourceDetailDTO> resourceDetailDTOList = new ArrayList<>();

        for (ResourceDetailDTO r : allResource) {
            boolean match = true;

            // 检查编号条件
            if (masterDataResource.getNumber() != null && !masterDataResource.getNumber().isEmpty()) {
                if (!masterDataResource.getNumber().equals(r.getResourceNumber())) {
                    match = false;
                }
            }

            // 检查名称条件
            if (masterDataResource.getName() != null && !masterDataResource.getName().isEmpty()) {
                if (!masterDataResource.getName().equals(r.getResourceName())) {
                    match = false;
                }
            }

            // 检查状态条件
            if (masterDataResource.getState() != null) {
                int state;
                switch (r.getResourceStatus()) {
                    case "未接房":
                        state = 0;
                        break;
                    case "空闲":
                        state = 1;
                        break;
                    case "已出租":
                        state = 2;
                        break;
                    default:
                        state = 3; // 处理其他未知状态
                        break;
                }
                if (!masterDataResource.getState().equals(state)) {
                    match = false;
                }
            }

            // 检查类型条件
            if (masterDataResource.getType() != null) {
                int type = r.getResourceType().equals("房屋") ? 0 : 1;
                if (!masterDataResource.getType().equals(type)) {
                    match = false;
                }
            }

            if (match) {
                resourceDetailDTOList.add(r);
            }
        }

        if (resourceDetailDTOList.isEmpty()) {
            throw new CustomException(NOT_FIND_DATA);
        }
        return getPageInfo(resourceDetailDTOList, masterDataResource.getPageNum(), masterDataResource.getPageSize());
    }


    // 拿到当前用户所属的组织的根节点并查询这个结点下的所有资源的方法
    public List<ResourceDetailDTO> getAllResource() {
        Object resourceList = masterDataRedisCache.getCacheObject("wyh:SearchResources:" + getCurrentUser().getId());
        if (resourceList != null) {
            return (List<ResourceDetailDTO>) resourceList;
        }
        List<MasterDataTreeNode> tree = masterDataTreeGenerate.generateResourceTree();
        MasterDataTreeNode rootNode = tree.get(0);
        // 拿到根结点的类型和id
        Integer id = rootNode.getId();
        String type = rootNode.getType();
        // 查询根结点下的所有资源
        MasterDataResourceTypeDTO masterDataResourceTypeDTO = new MasterDataResourceTypeDTO();
        masterDataResourceTypeDTO.setId(id);
        masterDataResourceTypeDTO.setType(type);
        List<ResourceDetailDTO> allDetails = getAllDetails(masterDataResourceTypeDTO);
        // 把数据存进redis
        masterDataRedisCache.setCacheObject("wyh:SearchResources:" + getCurrentUser().getId(), allDetails, 60, TimeUnit.MINUTES);
        return allDetails;
    }

    // 根据资源id查询缴费记录的业务方法
    @Override
    public List<PaymentHistory> getAllCharging(PaymentHistory paymentHistory) {
        if (paymentHistory == null) {
            throw new CustomException(PARAM_ERROR);
        }
        // 查询所有的缴费记录
        List<PaymentHistory> chargingList = masterDataResourceMapper.selectCharging(paymentHistory);
        return chargingList;
    }

    @Override
    public List<ThreeMeterInfo> getThreeMeterInfos(Integer id) {
        // 拿到本月的抄表时间，也就是上月一号
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime lastMonth = now.minusMonths(1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        String lastMonthString = lastMonth.format(formatter);
        YearMonth parse = YearMonth.parse(lastMonthString, formatter);
        LocalDateTime lastMonthLocalDateTime = parse.atDay(1).atStartOfDay();
        // 查询三表信息
        List<ThreeMeterInfo> threeMeterInfos = new ArrayList<>();
        List<Threemeter> threemeters = masterDataResourceMapper.selectThreemeterInfo(id);
        for (Threemeter t : threemeters) {
            Double previousReading = masterDataResourceMapper.selectReading(t.getId(), lastMonthLocalDateTime);
            ThreeMeterInfo threeMeterInfo = new ThreeMeterInfo();
            threeMeterInfo.setThreemeterId(t.getId());
            threeMeterInfo.setNature(t.getNature());
            threeMeterInfo.setNumber(t.getNumber());
            threeMeterInfo.setName(t.getName());
            threeMeterInfo.setMultiplier(t.getMultiplier());
            threeMeterInfo.setPreviousreading(previousReading);
            threeMeterInfo.setReportPeriod("每月一次");
            threeMeterInfo.setInfoname(t.getInfoName());
            threeMeterInfos.add(threeMeterInfo);
        }
        return threeMeterInfos;
    }

    // 停用（删除）三表信息的业务方法
    @Override
    public int deleteThreemeterById(Integer threemeterId) {
        if (threemeterId == null) {
            throw new CustomException(PARAM_ERROR);
        }
        return masterDataResourceMapper.deleteThreemeterInfo(threemeterId);
    }

    // 换表的方法
    @Override
    @Transactional
    public int replaceThreemeter(ThreeMeterInfo threeMeterInfo) {
        if (threeMeterInfo == null) {
            throw new CustomException(PARAM_ERROR);
        }
        // 1.修改原表的状态为-1，已删除
        masterDataResourceMapper.deleteThreemeterInfo(threeMeterInfo.getThreemeterId());

        // 2.在三表中插入新表数据
        Threemeter oldThreemeter = masterDataResourceMapper.selectThreemeter(threeMeterInfo.getThreemeterId());
        Threemeter threemeter = new Threemeter();
        threemeter.setNature(oldThreemeter.getNature());
        threemeter.setBelongingId(oldThreemeter.getBelongingId());
        threemeter.setNumber(threeMeterInfo.getNumber());
        threemeter.setName(threeMeterInfo.getName());
        threemeter.setInitial(threeMeterInfo.getInitial());
        threemeter.setCreationTime(LocalDateTime.now());
        threemeter.setUpdateTime(LocalDateTime.now());
        threemeter.setMultiplier(threeMeterInfo.getMultiplier());
        threemeter.setUpdateUser(getCurrentUser().getId());
        threemeter.setRemarks(oldThreemeter.getRemarks());
        threemeter.setInfoName(oldThreemeter.getInfoName());
        masterDataResourceMapper.insertThreemeter(threemeter);

        // 3.把插入的数据的id作为数据修改表中code的值
        masterDataResourceMapper.updateCodeById(threemeter.getId());

        // 4.在抄表表中插入新表的抄表数据
        Threemeter_Reading threemeterReading = new Threemeter_Reading();
        threemeterReading.setMeterId(threemeter.getId());
        threemeterReading.setReading(threeMeterInfo.getReading());
        threemeterReading.setUserid(getCurrentUser().getId());
        // 获取当前日期和时间
        LocalDateTime now = LocalDateTime.now();
        // 获取当前月的第一天
        LocalDateTime firstDayOfMonth = now.withDayOfMonth(1);
        threemeterReading.setTime(firstDayOfMonth);
        threemeterReading.setDosage(
                (threeMeterInfo.getReading() - threeMeterInfo.getPreviousreading()) * threeMeterInfo.getMultiplier()
        );
        masterDataResourceMapper.insertOldThreemeter(threemeterReading);
        return 0;
    }

    public List<ResourceCustomerDTO> selectResourceCustomer(Integer id) {
        //查询当前资源下的客户信息
        List<ResourceCustomerDTO> resourceCustomerDTOS = masterDataResourceMapper.selectResourceCustomer(id);
        return resourceCustomerDTOS;
    }

    public List<ResourceCustomerDTO> selectResourceCustomerHistory(Integer id) {
        //查询当前资源下客户的历史信息
        List<ResourceCustomerDTO> resourceCustomerDTOS = masterDataResourceMapper.selectResourceCustomerHistory(id);
        return resourceCustomerDTOS;
    }
}
